package com.dny.asmtop.op;

import com.dny.asmtop.Command;
import com.dny.asmtop.MethodContext;
import jdk.internal.org.objectweb.asm.Type;
import jdk.internal.org.objectweb.asm.commons.GeneratorAdapter;

import java.util.ArrayList;
import java.util.List;

import static jdk.internal.org.objectweb.asm.Type.VOID_TYPE;

/**
 * Created by jlutt on 2018-01-15.
 * 多个指令按顺序执行的方法体，
 * @author jlutt
 */
public class CommandSequence implements Command {

  private final List<Command> commands = new ArrayList<>();

  private CommandSequence() {

  }

  private CommandSequence(List<Command> expressions) {
    this.commands.addAll(expressions);
  }

  public static CommandSequence create() {
    return new CommandSequence();
  }

  public static CommandSequence create(List<Command> commands) {
    return new CommandSequence(commands);
  }

  public CommandSequence add(Command command) {
    commands.add(command);
    return this;
  }

  private Command getLast(List<Command> list) {
    return list.get(list.size() - 1);
  }

  @Override
  public Type type(MethodContext context) {
    Command expression = getLast(commands);
    return expression.type(context);
  }

  @Override
  public Type generator(MethodContext context) {
    GeneratorAdapter g = context.getGeneratorAdapter();

    Type type = VOID_TYPE;
    for (int i = 0; i < commands.size(); i++) {
      Command expression = commands.get(i);
      type = expression.generator(context);
      if (i != commands.size() - 1) {
        if (type.getSize() == 1)
          g.pop();
        if (type.getSize() == 2)
          g.pop2();
      }
    }

    return type;
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;

    CommandSequence that = (CommandSequence) o;

    return commands.equals(that.commands);
  }

  @Override
  public int hashCode() {
    return commands.hashCode();
  }
}
